import React, { useRef } from "react"
import { Component ,useComponentStore } from "../../editor/stores/components"
import { useComponentConfigStore } from "../../editor/stores/component-config"
import { message } from "antd"
import { ActionConfig } from "../Setting/ActionModal"


export function Preview() {
    const { components } = useComponentStore()
    const { componentConfigs } = useComponentConfigStore()

    const componentRefs = useRef<Record<string, any>>({})

    // 遍历组件配置的 events，然后从组件 props 找到该 event 对应的所有动作配置，
    // 都放到一个事件处理函数中 { onClick: () => {}, onDoubleClick: () => {} }
    function handleEvent(component: Component){
        const props: Record<string, any> = {}
        // 找出component-config 中该组件支持的事件（events）是否在 component 中使用了，如果有则处理
        componentConfigs[component.name]?.events?.forEach((event) => { // event:{name: 'onCllick', label: "点击事件"}
            // eventConfig: { "actions": [{"type": "goToLink","url": "http://baidu.com"}, { type: 'customJs',  code: "xxx" }]}
            const eventConfig = component.props[event.name]
            if (eventConfig) {
                props[event.name] = (...args: any[]) => {
                    eventConfig?.actions?.forEach((action: ActionConfig) => {
                        switch (action.type) {
                            case 'goToLink':
                                // action: {type: 'gotoLink', url: 'xxx'}
                                window.open(action.url, '_blank')
                                break;
                            case 'showMessage': 
                                // action: {type: 'showMessage', config: {type: 'success', text: 'xxx'}}
                                if (action.config.type === 'success') message.success(action.config.text)
                                else if (action.config.type === 'error') message.error(action.config.text)
                                break;
                            case 'customJs': 
                                // action: { type: 'customJs',  code: "xxx" }
                                
                                // 1. 定义函数 function func(参数1, 参数2，..., 函数体)
                                const func = new Function("context", 'args', action.code)

                                // 2. 执行函数
                                func({
                                    name: component.name,
                                    props: component.props,
                                    ShowMessage(content: string) {
                                        message.success(content)
                                    }
                                }, args)

                                break;
                            case 'componentMethod': 
                                // action: {type: 'componentMethod', config:{componentId:'xxx', method：'xxx'}}
                                const ref = componentRefs.current[action.config.componentId]
                                if (ref) {
                                    ref[action.config.method]?.(...args)
                                }
                                break;
                            default:
                                break;
                        }
                    })
                }
                
            }
        })
        console.log("事件", props)

        // { onclick: () => {} }
        return props
    }

    // 深度遍历 components, 根据组件名渲染对应的组件(components变化时都会重新渲染)
    function renderComponents(components: Component[]): React.ReactNode{
        return components.map(component => {
            const config = componentConfigs[component.name]
            if (!config?.prod) return null

            // 等同于调用组件，传递参数
            return React.createElement(config.prod, 
                {
                    key: component.id,
                    id: component.id,
                    name: component.name,
                    styles: component.styles,
                    ref: (ref: Record<string, any>) => {
                        componentRefs.current[component.id] = ref // 收集组件实例
                    },
                    ...config.defaultProps,
                    ...component.props,
                    ...handleEvent(component)
                },
                renderComponents(component.children || [])
            )
        })
    }

    return (
        <div className="Preview">
            { renderComponents(components) }
        </div>
    )
}